; 提供一些基础的函数
global out_port_byte
global set_idt_handler
global start_int
global system
global SYSCALL_HANDLE_TABLE
global in_port_byte

;=============================================
; 向端口写入值
; 入参：
;   esp+4 : 端口号
;   esp+8 : 值
; 对应rust原型:
;   fn out_port_byte(port : u16, value : u8);
out_port_byte:
    mov edx, [esp + 4]   ; 端口
    mov al, [esp + 8]   ; 值
    out dx, al
    nop
    nop
    ret

;=============================================
; 向端口读出值
; 入参：
;   esp+4 : 端口号
; 对应rust原型:
;   fn in_port_byte(port : u16) -> u8;
in_port_byte:
    mov edx, [esp + 4]   ; 端口
    xor eax, eax
    in al, dx
    nop
    nop
    ret

;==============================================
; IO延时
io_delay:
    nop
    nop
    nop
    nop
    ret

;==============================================
; 安装中断处理函数
; Rust原型：fn set_idt_handler(no : u8, handler : *const u8, arg_num : u8. attr: u8);
; 入参：
;   esp+4 : 中断向量号
;   esp+8 : 中断处理函数入口地址
;   esp+12 : 函数参数个数
;   esp+16 : 描述符属性
_IDT_BASE   equ     02000h
set_idt_handler:
    mov eax, [esp + 4]
    shl eax, 3                                  ; 根据中断向量号计算中断描述符相对于中断描述符表的偏移
   
    mov edx, [esp + 8]                          ; 中断处理函数
    mov word [_IDT_BASE + eax], dx              ; 段偏移的低16位
    shr edx, 16
    mov word [_IDT_BASE + eax + 6], dx          ; 段偏移的高16位

    mov edx, [esp + 16]
    mov byte [_IDT_BASE + eax + 5], dl          ; 属性

    mov edx, [esp + 12]
    and dl, 00011111b
    mov byte [_IDT_BASE + eax + 4], dl          ; 参数个数，低5位
    ret


;==============================================
; 开中断
start_int:
    sti
    ret

SYSCALL_HANDLE_TABLE    dd sys_get_ticks
                        dd 0

;==============================================
; 系统接口：理应在用户态，使用int指令，附带索引号参数
;           来调用中断处理函数，在用户态调用
;   esp+4 : 索引号
;   Rust原型：fn system(index: u32) -> u32;
system:
    mov eax, [esp + 4]
    int 080h
    ret

;==============================================
; 第一个系统接口调用：获取时钟ticks
extern _ticks
sys_get_ticks:
    mov eax, [_ticks]
    ret



